package mx.vlabs.jpautils.eao.bean;

import java.io.Serializable;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.Persistence;
import javax.persistence.PersistenceContext;

import mx.vlabs.jpautils.eao.api.EAOParams;
import mx.vlabs.jpautils.eao.api.EAOQueryBuilder;
import mx.vlabs.jpautils.eao.local.EAOLocal;
import mx.vlabs.jpautils.eo.EO;

import org.apache.log4j.Logger;

public class EAOBean<T extends EO<PK>,PK extends Serializable> implements EAOLocal<T, PK> {
	
	private Logger log = Logger.getLogger(EAOBean.class);
	
	private Class<T> entityClass;
	

	private EAOQueryBuilder<T,PK> queryBuilder;
	
	@PersistenceContext
	private EntityManager em;
	
	public EAOBean(Class<T> entityClass){
		super();
		log.info("initializing bean");
		this.entityClass = entityClass;
		
	}
	
	@PostConstruct
	public void initBean(){
		queryBuilder = new EAOQueryBuilder<T,PK>(entityClass,getEntityManager());
	}
	
	public EntityManager getEntityManager(){
		return em;
	}
	
	@Override
	public T get(PK id) {
		// TODO Auto-generated method stub
		return getEntityManager().find(entityClass, id);
	}

	@SuppressWarnings("unchecked")
	@Override
	public T find(EAOParams conditions) {
		// TODO Auto-generated method stub
		EAOParams params = new EAOParams();
		params.put(EAOQueryBuilder.COUNT_KEY, false);
		params.put(EAOQueryBuilder.CONDITIONS_KEY, conditions);
		
		return (T) queryBuilder.build(params).getSingleResult();
	}

	@Override
	public List<T> findAll(EAOParams params) {
		params.put(EAOQueryBuilder.COUNT_KEY, false);
		return queryBuilder.build(params).getResultList();
	}
	
	@Override
	public long count(EAOParams params){
		params.put(EAOQueryBuilder.COUNT_KEY, true);
		return Long.parseLong(queryBuilder.build(params).getSingleResult().toString());
	}
	
	@Override
	public T save(T eo) {
		// TODO Auto-generated method stub
		return save(eo,false);
	}

	@Override
	public T save(T eo, boolean flush) {
		// TODO Auto-generated method stub
		if(eo!=null){
			
			if(eo.getId()==null){
				getEntityManager().persist(eo);
			}else{
				getEntityManager().merge(eo);
			}
			
			if(flush) flush();
			
			return eo;
		}else{
			return null;
		}
	}

	@Override
	public void flush() {
		// TODO Auto-generated method stub
		getEntityManager().flush();
	}


	@Override
	public PK delete(PK id) {
		// TODO Auto-generated method stub
		getEntityManager().remove(get(id));

		return id;
	}

	@Override
	public List<T> list() {
		// TODO Auto-generated method stub
		return getEntityManager().createQuery("select "+entityClass.getSimpleName()+" from "+entityClass.getName()+" "+entityClass.getSimpleName()).getResultList();
	}

}
